/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.saashousekeeper.interceptor;

import com.huawei.saashousekeeper.config.TenantContext;
import com.huawei.saashousekeeper.config.adapter.SchemaAdapter;
import com.huawei.saashousekeeper.constants.Constants;
import com.huawei.saashousekeeper.exception.RoutingException;

import lombok.extern.log4j.Log4j2;

import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerExceptionResolver;

import java.util.Objects;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 租户标识过滤器
 *
 * @author lWX1128557
 * @since 2022-04-01
 */
@Log4j2
@RefreshScope
public class TenantDomainFilter implements Filter, Ordered {

    @Autowired
    private SchemaAdapter schemaAdapter;

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        log.info("----TenantDomainFilter----");
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String tenantDomain = request.getHeader("tenantDomain");

            log.info("tenantDomain:{}", tenantDomain);
            log.info("schemaAdapter:{}", schemaAdapter);

            // MDC埋点
            MDC.put(Constants.TENENT_ID, tenantDomain);
            TenantContext.setDomain(tenantDomain);

            try {
                if (Objects.isNull(schemaAdapter.getSchema(tenantDomain))) {
                    throw new RoutingException("Routing failure,The corresponding database could not be found");
                }
                filterChain.doFilter(request, response);
            } catch (RoutingException e) {
                resolver.resolveException(request, response, null, e);
            } catch (Exception e) {
                resolver.resolveException(request, response, null, e);
            } finally {
                MDC.clear();
                TenantContext.remove();
            }
    }
}
